# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# @Time    : 2022/9/1
# @Author  : moe@miku39.fun
# @File    : VideoAbstraction.py
# @Software: PyCharm
import abc
import re


class VideoAbstraction(metaclass=abc.ABCMeta):
    def __init__(self, sess):
        self.videoBaseInfo = None
        self.sess = sess
        self.videoQuality = None
        self.audioQuality = None
        self.allowVideoSet = set()
        self.videoSourceList = []

    @abc.abstractmethod
    def getVideoInfo(self, video):
        pass

    def printEP(self, new_pages):
        if self.videoBaseInfo["videoType"] == "animeFilm":
            print(
                [
                    f"{index}: {elem['long_title']}"
                    if elem["long_title"]
                    else f"{index}: {elem['title']}"
                    for index, elem in new_pages.items()
                ],
                "\n",
            )
        else:
            print([f"{i}: {elem['part']}" for i, elem in new_pages.items()], "\n")

    @classmethod
    def confirmInfo(cls):
        print("请认真核对以上视频信息，并做出你的选择 (=・ω・=)")
        while True:
            if choice := input("是否立即下载[Y/N](default: Y):"):
                if re.match("y", choice, re.I):
                    return True
                elif re.match("n", choice, re.I):
                    return False
                else:
                    print("输入有误 Σ(ﾟдﾟ;)")
            else:
                return True

    def choiceVideo(self, pages):
        if self.videoBaseInfo["videoType"] == "animeFilm":
            newPages = dict(enumerate(pages, 1))
        else:
            newPages = dict(enumerate(pages, 1))
        if (length := len(newPages)) > 1:
            resultList = []
            print("提示: 建议最多提交10个分P号，任务过多可能被限速 _(≧∇≦」∠)_")
            self.printEP(newPages)
            while True:
                needs = []
                if result := input(
                    "请输入视频分P号(num) 或 指定范围分P号(start-end) 以空格隔开(default: all):"
                ):
                    tmp = [
                        needs.append(int(i)) if i.isdigit() else i
                        for i in result.split()
                    ]  # 筛选数字
                    tmp2 = [j.split("-") for j in tmp if type(j) is str]  # 筛选范围
                    [
                        needs.extend(range(int(k[0]), int(k[-1]) + 1)) for k in tmp2
                    ]  # 生成范围
                    needSet = set(needs)
                    for i in range(1, length + 1):
                        if i in needSet:
                            resultList.append(newPages[i])
                    if resultList:
                        return resultList
                    else:
                        print("您选择的分P号不存在哦，请重新选择 ('▔□▔)/")
                        resultList.clear()
                else:
                    return newPages.values()
        else:
            return newPages.values()

    def choiceVideo2(self, pages, episodes):
        if self.videoBaseInfo["videoType"] == "animeFilm":
            newPages = dict(enumerate(pages, 1))
        else:
            newPages = dict(enumerate(pages, 1))
        if episodes:
            needs = []
            resultList = []
            length = len(newPages)
            tmp = [
                needs.append(int(i)) if i.isdigit() else i for i in episodes.split(",")
            ]  # 筛选数字
            tmp2 = [j.split("-") for j in tmp if type(j) is str]  # 筛选范围
            [needs.extend(range(int(k[0]), int(k[-1]) + 1)) for k in tmp2]  # 生成范围
            needSet = set(needs)
            for i in range(1, length + 1):
                if i in needSet:
                    resultList.append(newPages[i])
            if resultList:
                return resultList
            else:
                print("您选择的分P号不存在哦，请重新运行 ('▔□▔)/")
                return False
        else:
            return newPages.values()

    @classmethod
    def getQualityMap(cls):
        audioQuality = {30280: "高音质", 30232: "中音质", 30216: "低音质"}
        videoQuality = {
            127: "8K 超高清",
            125: "HDR 真彩",
            120: "超清 4K",
            116: "60帧 1080P",
            112: "高码率 1080P",
            80: "高清 1080P",
            74: "60帧 720P",
            64: "高清 720P",
            32: "清晰 480P",
            16: "流畅 360P",
        }
        return audioQuality, videoQuality

    @classmethod
    def __choiceQuality(cls, string, quality):
        print(f"\n{string}列表")
        print(quality)
        while True:
            choice = input(f"请选择预下载的视频{string}(default: bestQuality):")
            if choice.isdigit():
                if int(choice) in quality:
                    return int(choice)
                else:
                    print(f"{string}不存在 (._.`)")
            else:
                return max(quality.keys())

    def choiceQuality(self):
        # 后续还用得到，因提升为实例变量
        for key in self.videoQuality.keys() - self.allowVideoSet:
            self.videoQuality.pop(key, None)
        print(f"\n画质'高于'1080P需大会员支持!\n若指定画质或音质不存在，将自动选择最高质量")
        video = VideoAbstraction.__choiceQuality("画质", self.videoQuality)
        audio = VideoAbstraction.__choiceQuality("音质", self.audioQuality)
        return video, audio

    def choiceQuality2(self):
        for key in self.videoQuality.keys() - self.allowVideoSet:
            self.videoQuality.pop(key, None)
        video = VideoAbstraction.__choiceQuality("画质", self.videoQuality)
        audio = VideoAbstraction.__choiceQuality("音质", self.audioQuality)
        return video, audio

    @classmethod
    def getSourceList(cls, source):
        sourceList = []
        if baseUrl := source.get("baseUrl", None):
            sourceList.append(baseUrl)
        if base_url := source.get("base_url", None):
            sourceList.append(base_url)
        if backupUrl := source.get("backupUrl", None):
            sourceList.extend(backupUrl)
        if backup_url := source.get("backup_url", None):
            sourceList.extend(backup_url)
        return sourceList

    @abc.abstractmethod
    def getVideoPageInfo(self, dic):
        pass

    @classmethod
    def __encapsulateData(cls, resource, quality):
        for each in resource:
            if each["id"] == quality:
                resource = each
                break
        else:
            resource = resource[0]
        return resource

    def encapsulateData(self, video_quality, audio_quality):
        for each in self.videoSourceList:
            each["video"] = VideoAbstraction.__encapsulateData(each["video"], video_quality)
            each["audio"] = VideoAbstraction.__encapsulateData(each["audio"], audio_quality)

    def getVideoPlayUrl(self, video_base_info, video_info):
        self.videoBaseInfo = video_base_info
        self.audioQuality, self.videoQuality = VideoAbstraction.getQualityMap()
        while True:
            pages = self.choiceVideo(video_info["pages"])
            for sub in pages:
                self.getVideoPageInfo(sub)
            videoQuality, audioQuality = self.choiceQuality()
            self.encapsulateData(videoQuality, audioQuality)
            for each in self.videoSourceList:
                print(
                    f"> 视频名称: {each['title']}\t视频画质: {each['video']['quality']}\t视频音质: {each['audio']['quality']}"
                )
            if VideoAbstraction.confirmInfo():
                return self.videoSourceList
            self.videoSourceList = []

    def getVideoPlayUrl2(self, video_base_info, video_info, video_base_data):
        self.videoBaseInfo = video_base_info
        self.audioQuality, self.videoQuality = VideoAbstraction.getQualityMap()
        if pages := self.choiceVideo2(video_info["pages"], video_base_data["episodes"]):
            for sub in pages:
                self.getVideoPageInfo(sub)
            videoQuality, audioQuality = (
                video_base_data["videoQuality"],
                video_base_data["audioQuality"],
            )
            self.encapsulateData(videoQuality, audioQuality)
            if video_base_data["yes"]:  # -y 选项
                return self.videoSourceList
            for each in self.videoSourceList:
                print(
                    f"> 视频名称: {each['title']}\t视频画质: {each['video']['quality']}\t视频音质: {each['audio']['quality']}"
                )
            if VideoAbstraction.confirmInfo():
                return self.videoSourceList
        return False
